package tx.algoritmiek.week2;

import java.util.ArrayList;
import java.util.List;


public class BinaryTree {

    private Node root;

    public BinaryTree(Node root) {
        this.root = root;
    }

    public void add(Object o) {

    }

    public void remove(Object o) {

    }

    public List<GameObject> find(int[] coordinate) {
        List<GameObject> matchingNodes = new ArrayList<GameObject>();

        this.search(coordinate, 0, root, matchingNodes);

        return matchingNodes;
    }

    private boolean search(int[] coordinate, int nCoord, Node currentNode, List<GameObject> matchingNodes) {
        if(currentNode instanceof EndNode) {
            //Check if all coordinates are valid
            for(int i = 0; i < coordinate.length; i++) {
                if(currentNode.getLowerBound(i) < coordinate[i] || 
                        currentNode.getUpperBound(i) > coordinate[i]) {
                    return false;
                }
            }
//            System.out.println("FOUND!");
            matchingNodes.add(((EndNode)currentNode).getGameObject());
            return true;
        } else {
            SplitNode temp = (SplitNode)currentNode;
            
//            System.out.println("-------------------------");
//            System.out.println("Looking at nCoord: " + nCoord);
//            System.out.println("LeftChild: " + temp.getLeftChild().getLowerBound(nCoord) 
//                    + " - " + temp.getLeftChild().getUpperBound(nCoord));
//            System.out.println("RightChild: " + temp.getRightChild().getLowerBound(nCoord) 
//                    + " - " + temp.getRightChild().getUpperBound(nCoord));
            
            //Check if coordinates are within the left child bounds
            if(coordinate[nCoord] >= temp.getLeftChild().getLowerBound(nCoord) &&
                    coordinate[nCoord] <= temp.getLeftChild().getUpperBound(nCoord)) {
//                System.out.println("Looking at LeftChild");

                //Search through the left child
                boolean result = this.search(coordinate, (nCoord+1) % 2, 
                        temp.getLeftChild(), matchingNodes);
                //Also check the right child in case the left one matches 
                if(result) {
                    this.search(coordinate, (nCoord+1) % 2, 
                            temp.getRightChild(), matchingNodes);
                } 
            } 
            if(coordinate[nCoord] >= temp.getRightChild().getLowerBound(nCoord) &&
                    coordinate[nCoord] <= temp.getRightChild().getUpperBound(nCoord)) {
//                System.out.println("Looking at RightChild");
                this.search(coordinate, (nCoord+1) % 2, 
                        temp.getRightChild(), matchingNodes);
            }
            return false;
        }
    }

    public void setRoot(Node root) {
        this.root = root;
    }

    public Node getRoot() {
        return root;
    }

    public void setBoundArraysInTree() {
        if(root instanceof SplitNode) {
            this.setBoundArraysInTree((SplitNode)root);
        }
    }

    private void setBoundArraysInTree(SplitNode node) {
        Node left = node.getLeftChild();
        Node right = node.getRightChild();

        if(left instanceof SplitNode) {
            this.setBoundArraysInTree((SplitNode)left);
            ((SplitNode)left).setBoundArrays(0);
        }
        if(right instanceof SplitNode) {   
            this.setBoundArraysInTree((SplitNode)right);
            ((SplitNode)right).setBoundArrays(0);                        
        }
    }
}
